const getProto = Object.getPrototypeOf, class2type = {}, toString = class2type.toString, hasOwn = class2type.hasOwnProperty;

// 获取类型
const toType = function toType(obj) {
  let reg = /^\[object (.+)\]$/;
  if(obj === null) return obj + "";
  return typeof obj === 'object' || typeof obj === 'function' ? 
    reg.exec(toString.call(obj)[1].toLowerCase()) : typeof obj;
}

// 是不是纯对象
const isPlainObject = function isPlainObject(obj) {
  let proto, Ctro;
  if(!obj || toString.call(obj) !== "[object Object]") return false;
  proto = getProto(obj);
  if(!proto) return true;
  Ctor = hasOwn.call(proto, 'constructor') && proto.constructor;
  return typeof Ctro === 'function' && Ctro === Object;
}

// 是不是函数
const isFunction = function isFunction(obj) {
  return typeof obj === 'function' && typeof obj.nodeType !== 'number' && typeof obj.item !== 'function';
}

const isWindow = function isWindow(obj) {
  return obj != null && obj === obj.window;
}

const isEmptyObject = function isEmptyObject(obj) {
  if (obj == null || !/^(object|function)$/.test(typeof obj)) return false;
  let keys = Object.getOwnPropertyNames(obj);
  if (typeof Symbol !== 'undefined') keys = keys.concat(Object.getOwnPropertySymbols(obj));
  return keys.length === 0;
}

const isArrayLike = function isArrayLike(obj) {
  let length = !!obj && "length" in obj && obj.length, type = toType(obj);
  if (isFunction(obj) || isWindow(obj)) return false;
  return type === 'array' || length === 0 || typeof length === 'number' && length > 0 && (length - 1) in obj;
}

// 迭代方法：迭代数组、类数组、对象
function each(obj, callback) {
  if(obj === null || !/^object$/.test(typeof obj)) throw new TypeError('obj must be object/array/likearray');
  if(typeof callback !== 'function') throw new TypeError('callback is not a function');
  let item, keys, key;
  if(isArrayLike(obj)) {
    for(let i = 0; i < obj.length; i++) {
      item = obj[i];
      if (callback.call(item, item, i) === false) break;
    }
  } else {
    keys = Object.getOwnPropertyNames(obj);
    if (typeof Symbol !== 'undefined') keys = keys.concat(Object.getOwnPropertySymbols(obj));
    for(let i = 0; i < keys.length; i++) {
      key = keys[i];
      item = obj[key];
      if (callback.call(item, item, key) === false) break;
    }
  }
  return obj;
}

// 深浅拷贝

// 对象合并

// 交换数组两个元素
function swap(index1, index2, arr) {
    arr[index1] = arr.splice(index2, 1, arr[index1])[0];
    return arr;
}